From 259afe8ad4007af66e14d602002b5865eace81db Mon Sep 17 00:00:00 2001 From: tsteven4 <13596209+tsteven4@users.noreply.github.com> Date: Mon, 2 Dec 2019 09:34:28 -0700 Subject: [PATCH] using QStrings in filter and format vecs. (#428) This includes: our format list entry vecs_t, out filter list entry fl_vecs_t and our format interface ff_vecs_t. Fix validation of options supplied with a format or filter. Previously unknown options were only detected if all given options were unknown. Now any unknown option will be reported, irregardless of any other options supplied. The behavoir of ignoring unknown options is unchanged, they are ignored except for the warning. --- defs.h | 17 ++-- filter_vecs.cc | 77 ++++++++-------- filterdefs.h | 4 +- garmin.cc | 3 +- inifile.cc | 4 +- inifile.h | 4 +- magproto.cc | 3 +- main.cc | 13 ++- testo.d/bend.test | 2 +- vecs.cc | 222 +++++++++++++++++++++------------------------- 10 files changed, 162 insertions(+), 187 deletions(-) diff --git a/defs.h b/defs.h index 5dee01c2f..75200c4b0 100644 --- a/defs.h +++ b/defs.h @@ -920,7 +920,7 @@ using ff_exit = void (*)(); using ff_writeposn = void (*)(Waypoint*); using ff_readposn = Waypoint* (*)(posn_status*); -char* get_option(const char* iarglist, const char* argname); +QString get_option(const QStringList& options, const char* argname); geocache_type gs_mktype(const QString& t); geocache_container gs_mkcont(const QString& t); @@ -1050,10 +1050,10 @@ struct ff_vecs_t { ff_write write; ff_exit exit; arglist_t* args; - const char* encode; + QString encode; int fixed_encode; position_ops_t position_ops; - const char* name; /* dyn. initialized by find_vec */ + QString name; /* dyn. initialized by find_vec */ }; struct style_vecs_t { @@ -1067,12 +1067,13 @@ void is_fatal(int condition, const char*, ...) PRINTFLIKE(2, 3); void warning(const char*, ...) PRINTFLIKE(1, 2); void debug_print(int level, const char* fmt, ...) PRINTFLIKE(2,3); -ff_vecs_t* find_vec(const char*, const char**); -void assign_option(const char* vecname, arglist_t* ap, const char* val); -void disp_vec_options(const char* vecname, arglist_t* ap); +ff_vecs_t* find_vec(const QString&); +void assign_option(const QString& vecname, arglist_t* ap, const char* val); +void disp_vec_options(const QString& vecname, const arglist_t* ap); void disp_vecs(); -void disp_vec(const char* vecname); -bool validate_args(const char* vecname, arglist_t* ap); +void disp_vec(const QString& vecname); +void validate_options(const QStringList& options, const arglist_t* args, const QString& name); +bool validate_args(const QString& name, const arglist_t* args); bool validate_formats(); void init_vecs(); void exit_vecs(); diff --git a/filter_vecs.cc b/filter_vecs.cc index aca6120a2..700094a4b 100644 --- a/filter_vecs.cc +++ b/filter_vecs.cc @@ -43,19 +43,21 @@ #include "gbversion.h" #include "inifile.h" +#include // for QByteArray #include // for QString #include // for QStringList #include // for QVector<>::iterator, QVector #include // for CaseInsensitive +#include // for qPrintable #include // for sort #include // for printf -#include // for strchr + struct fl_vecs_t { Filter* vec; - const char* name; - const char* desc; + QString name; + QString desc; }; ArcDistanceFilter arcdist; @@ -170,8 +172,7 @@ const QVector filter_vec_list = { &validate, "validate", "Validate internal data structures" - }, - + } #elif defined (MINIMAL_FILTERS) { &trackfilter, @@ -182,18 +183,24 @@ const QVector filter_vec_list = { }; Filter* -find_filter_vec(const char* const vecname, const char** opts) +find_filter_vec(const QString& vecname) { - const QString svecname = QString(vecname).split(',').at(0); - int found = 0; + QStringList options = vecname.split(','); + if (options.isEmpty()) { + fatal("A filter name is required.\n"); + } + const QString svecname = options.takeFirst(); for (const auto& vec : filter_vec_list) { - if (svecname.compare(vec.name, Qt::CaseInsensitive)) { + if (svecname.compare(vec.name, Qt::CaseInsensitive) != 0) { continue; } - /* step 1: initialize by inifile or default values */ arglist_t* args = vec.vec->get_args(); + + validate_options(options, args, vec.name); + + /* step 1: initialize by inifile or default values */ if (args) { for (auto ap = args; ap->argstring; ap++) { QString qtemp = inifile_readstr(global_opts.inifile, vec.name, ap->argstring); @@ -209,25 +216,15 @@ find_filter_vec(const char* const vecname, const char** opts) } /* step 2: override settings with command-line values */ - const char* res = strchr(vecname, ','); - if (res) { - *opts = res+1; - + if (!options.isEmpty()) { if (args) { for (auto ap = args; ap->argstring; ap++) { - char* opt = get_option(*opts, ap->argstring); - if (opt) { - found = 1; - assign_option(vec.name, ap, opt); - xfree(opt); + const QString opt = get_option(options, ap->argstring); + if (!opt.isNull()) { + assign_option(vec.name, ap, CSTR(opt)); } } } - } else { - *opts = nullptr; - } - if (opts && opts[0] && !found) { - warning("'%s' is an unknown option to %s.\n", *opts, vec.name); } if (global_opts.debug_level >= 1) { @@ -246,7 +243,7 @@ free_filter_vec(Filter* filter) arglist_t* args = filter->get_args(); if (args) { - for (arglist_t* ap = args; ap->argstring; ap++) { + for (auto ap = args; ap->argstring; ap++) { if (ap->argvalptr) { xfree(ap->argvalptr); ap->argvalptr = *ap->argval = nullptr; @@ -261,7 +258,7 @@ init_filter_vecs() for (const auto& vec : filter_vec_list) { arglist_t* args = vec.vec->get_args(); if (args) { - for (arglist_t* ap = args; ap->argstring; ap++) { + for (auto ap = args; ap->argstring; ap++) { ap->argvalptr = nullptr; } } @@ -285,9 +282,9 @@ disp_filter_vecs() { for (const auto& vec : filter_vec_list) { printf(" %-20.20s %-50.50s\n", - vec.name, vec.desc); + qPrintable(vec.name), qPrintable(vec.desc)); arglist_t* args = vec.vec->get_args(); - for (arglist_t* ap = args; ap && ap->argstring; ap++) { + for (auto ap = args; ap && ap->argstring; ap++) { if (!(ap->argtype & ARGTYPE_HIDDEN)) printf(" %-18.18s %-.50s %s\n", ap->argstring, ap->helpstring, @@ -297,16 +294,16 @@ disp_filter_vecs() } void -disp_filter_vec(const char* vecname) +disp_filter_vec(const QString& vecname) { for (const auto& vec : filter_vec_list) { - if (case_ignore_strcmp(vec.name, vecname)) { + if (vecname.compare(vec.name, Qt::CaseInsensitive) != 0) { continue; } printf(" %-20.20s %-50.50s\n", - vec.name, vec.desc); + qPrintable(vec.name), qPrintable(vec.desc)); arglist_t* args = vec.vec->get_args(); - for (arglist_t* ap = args; ap && ap->argstring; ap++) { + for (auto ap = args; ap && ap->argstring; ap++) { if (!(ap->argtype & ARGTYPE_HIDDEN)) printf(" %-18.18s %-.50s %s\n", ap->argstring, ap->helpstring, @@ -316,11 +313,11 @@ disp_filter_vec(const char* vecname) } static -void disp_help_url(const fl_vecs_t& vec, arglist_t* arg) +void disp_help_url(const fl_vecs_t& vec, const arglist_t* arg) { - printf("\t" WEB_DOC_DIR "/fmt_%s.html", vec.name); + printf("\t" WEB_DOC_DIR "/fmt_%s.html", CSTR(vec.name)); if (arg) { - printf("#fmt_%s_o_%s",vec.name, arg->argstring); + printf("#fmt_%s_o_%s", CSTR(vec.name), arg->argstring); } } @@ -330,10 +327,10 @@ disp_v1(const fl_vecs_t& vec) disp_help_url(vec, nullptr); printf("\n"); arglist_t* args = vec.vec->get_args(); - for (arglist_t* ap = args; ap && ap->argstring; ap++) { + for (auto ap = args; ap && ap->argstring; ap++) { if (!(ap->argtype & ARGTYPE_HIDDEN)) { printf("option\t%s\t%s\t%s\t%s\t%s\t%s\t%s", - vec.name, + CSTR(vec.name), ap->argstring, ap->helpstring, name_option(ap->argtype), @@ -357,7 +354,7 @@ disp_filters(int version) auto sorted_filter_vec_list = filter_vec_list; auto alpha = [](const fl_vecs_t& a, const fl_vecs_t& b)->bool { - return case_ignore_strcmp(a.desc, b.desc) < 0; + return QString::compare(a.desc, b.desc, Qt::CaseInsensitive) < 0; }; std::sort(sorted_filter_vec_list.begin(), sorted_filter_vec_list.end(), alpha); @@ -367,9 +364,9 @@ disp_filters(int version) case 1: for (const auto& vec : sorted_filter_vec_list) { if (version == 0) { - printf("%s\t%s\n", vec.name, vec.desc); + printf("%s\t%s\n", CSTR(vec.name), CSTR(vec.desc)); } else { - printf("%s\t%s", vec.name, vec.desc); + printf("%s\t%s", CSTR(vec.name), CSTR(vec.desc)); disp_v1(vec); } } diff --git a/filterdefs.h b/filterdefs.h index cfed0ed94..49efa99c2 100644 --- a/filterdefs.h +++ b/filterdefs.h @@ -47,10 +47,10 @@ struct filter_vecs_t { arglist_t* args; }; -Filter* find_filter_vec(const char* const, const char**); +Filter* find_filter_vec(const QString&); void free_filter_vec(Filter*); void disp_filters(int version); -void disp_filter_vec(const char* vecname); +void disp_filter_vec(const QString& vecname); void disp_filter_vecs(); void init_filter_vecs(); void exit_filter_vecs(); diff --git a/garmin.cc b/garmin.cc index f46de6657..09adc9c8d 100644 --- a/garmin.cc +++ b/garmin.cc @@ -342,9 +342,8 @@ static void rd_init(const QString& fname) { if (setjmp(gdx_jmp_buf)) { - const char* vec_opts = nullptr; const gdx_info* gi = gdx_get_info(); - gpx_vec = find_vec("gpx", &vec_opts); + gpx_vec = find_vec("gpx"); gpx_vec->rd_init(gi->from_device.canon); } else { gpx_vec = nullptr; diff --git a/inifile.cc b/inifile.cc index 6fbeb7c80..0c385c230 100644 --- a/inifile.cc +++ b/inifile.cc @@ -216,7 +216,7 @@ inifile_has_section(const inifile_t* inifile, const char* section) */ QString -inifile_readstr(const inifile_t* inifile, const char* section, const char* key) +inifile_readstr(const inifile_t* inifile, const QString& section, const QString& key) { return inifile_find_value(inifile, section, key); } @@ -228,7 +228,7 @@ inifile_readstr(const inifile_t* inifile, const char* section, const char* key) */ int -inifile_readint(const inifile_t* inifile, const char* section, const char* key, int* value) +inifile_readint(const inifile_t* inifile, const QString& section, const QString& key, int* value) { const QString str = inifile_find_value(inifile, section, key); diff --git a/inifile.h b/inifile.h index d45cd579a..f428caa93 100644 --- a/inifile.h +++ b/inifile.h @@ -46,14 +46,14 @@ bool inifile_has_section(const inifile_t* inifile, const char* section); returns a null QString if not found, otherwise a non-null but possibly empty Qstring with the value of key ... */ -QString inifile_readstr(const inifile_t* inifile, const char* section, const char* key); +QString inifile_readstr(const inifile_t* inifile, const QString& section, const QString& key); /* inifile_readint: on success the value is stored into "*value" and "inifile_readint" returns 1, otherwise inifile_readint returns 0 */ -int inifile_readint(const inifile_t* inifile, const char* section, const char* key, int* value); +int inifile_readint(const inifile_t* inifile, const QString& section, const QString& key, int* value); /* inifile_readint_def: diff --git a/magproto.cc b/magproto.cc index 5968f955f..a0560a082 100644 --- a/magproto.cc +++ b/magproto.cc @@ -785,8 +785,7 @@ mag_rd_init_common(const QString& portname) const char** dlist = os_get_magellan_mountpoints(); explorist_info = explorist_ini_get(dlist); if (explorist_info) { - const char* vec_opts = nullptr; - gpx_vec = find_vec("gpx", &vec_opts); + gpx_vec = find_vec("gpx"); } return; } diff --git a/main.cc b/main.cc index fd85021be..5786b384c 100644 --- a/main.cc +++ b/main.cc @@ -158,7 +158,7 @@ usage(const char* pname, int shorter) } static void -spec_usage(const char* vec) +spec_usage(const QString& vec) { printf("\n"); disp_vec(vec); @@ -206,9 +206,6 @@ run(const char* prog_name) Filter* filter = nullptr; QString fname; QString ofname; - const char* ivec_opts = nullptr; - const char* ovec_opts = nullptr; - const char* fvec_opts = nullptr; int opt_version = 0; bool did_something = false; WaypointList* wpt_head_bak; @@ -251,7 +248,7 @@ run(const char* prog_name) if (qargs.at(argn).size() > 1 && (qargs.at(argn).at(1).toLatin1() == '?' || qargs.at(argn).at(1).toLatin1() == 'h')) { if (argn < qargs.size()-1) { - spec_usage(qPrintable(qargs.at(argn+1))); + spec_usage(qargs.at(argn+1)); } else { usage(prog_name,0); } @@ -267,7 +264,7 @@ run(const char* prog_name) switch (c) { case 'i': optarg = FETCH_OPTARG; - ivecs = find_vec(CSTR(optarg), &ivec_opts); + ivecs = find_vec(optarg); if (ivecs == nullptr) { fatal("Input type '%s' not recognized\n", qPrintable(optarg)); } @@ -277,7 +274,7 @@ run(const char* prog_name) warning("-o appeared before -i. This is probably not what you want to do.\n"); } optarg = FETCH_OPTARG; - ovecs = find_vec(CSTR(optarg), &ovec_opts); + ovecs = find_vec(optarg); if (ovecs == nullptr) { fatal("Output type '%s' not recognized\n", qPrintable(optarg)); } @@ -407,7 +404,7 @@ run(const char* prog_name) break; case 'x': optarg = FETCH_OPTARG; - filter = find_filter_vec(CSTR(optarg), &fvec_opts); + filter = find_filter_vec(optarg); if (filter) { filter->init(); diff --git a/testo.d/bend.test b/testo.d/bend.test index 843376e85..bf6e81a82 100644 --- a/testo.d/bend.test +++ b/testo.d/bend.test @@ -1,5 +1,5 @@ rm -f ${TMPDIR}/bend.* -gpsbabel -i gpx -f ${REFERENCE}/route/bend-input.gpx -x bend,distance=25,interpolate,minangle=5 -o gpx -F ${TMPDIR}/bend.gpx +gpsbabel -i gpx -f ${REFERENCE}/route/bend-input.gpx -x bend,distance=25,minangle=5 -o gpx -F ${TMPDIR}/bend.gpx compare ${REFERENCE}/route/bend-expected.gpx ${TMPDIR}/bend.gpx diff --git a/vecs.cc b/vecs.cc index 4cd6b8078..ec4b9b4c3 100644 --- a/vecs.cc +++ b/vecs.cc @@ -19,14 +19,19 @@ */ -#include -#include +#include // for QByteArray +#include // for QString +#include // for QStringList +#include // for QVector<>::iterator, QVector +#include // for CaseInsensitive +#include // for qPrintable #include // for sort +#include // for assert +#include // for isdigit #include // for printf, putchar, sscanf, size_t #include #include // for strchr, strtok, memset, strlen -#include // for isdigit #include "defs.h" #include "gbversion.h" // for WEB_DOC_DIR @@ -39,10 +44,10 @@ struct vecs_t { ff_vecs_t* vec; - const char* name; + QString name; QString desc; QString extensions; // list of possible extensions separated by '/', first is output default for GUI. - const char* parent; + QString parent; }; extern ff_vecs_t an1_vecs; @@ -1136,12 +1141,12 @@ exit_vecs() } void -assign_option(const char* module, arglist_t* ap, const char* val) +assign_option(const QString& module, arglist_t* ap, const char* val) { const char* c; if (ap->argval == nullptr) { - fatal("%s: No local variable defined for option \"%s\"!", module, ap->argstring); + fatal("%s: No local variable defined for option \"%s\"!", qPrintable(module), ap->argstring); } if (ap->argvalptr != nullptr) { @@ -1172,7 +1177,7 @@ assign_option(const char* module, arglist_t* ap, const char* val) } else { int test; is_fatal(1 != sscanf(c, "%d", &test), - "%s: Invalid parameter value %s for option %s", module, val, ap->argstring); + "%s: Invalid parameter value %s for option %s", qPrintable(module), val, ap->argstring); } break; case ARGTYPE_FLOAT: @@ -1181,7 +1186,7 @@ assign_option(const char* module, arglist_t* ap, const char* val) } else { double test; is_fatal(1 != sscanf(c, "%lf", &test), - "%s: Invalid parameter value %s for option %s", module, val, ap->argstring); + "%s: Invalid parameter value %s for option %s", qPrintable(module), val, ap->argstring); } break; case ARGTYPE_BOOL: @@ -1205,7 +1210,7 @@ assign_option(const char* module, arglist_t* ap, const char* val) c = "1"; } } else { - warning(MYNAME ": Invalid logical value '%s' (%s)!\n", c, module); + warning(MYNAME ": Invalid logical value '%s' (%s)!\n", c, qPrintable(module)); c = "0"; } break; @@ -1224,12 +1229,12 @@ assign_option(const char* module, arglist_t* ap, const char* val) } void -disp_vec_options(const char* vecname, arglist_t* ap) +disp_vec_options(const QString& vecname, const arglist_t* ap) { for (; ap && ap->argstring; ap++) { if (*ap->argval && ap->argval) { printf("options: module/option=value: %s/%s=\"%s\"", - vecname, ap->argstring, *ap->argval); + qPrintable(vecname), ap->argstring, *ap->argval); if (ap->defaultvalue && (case_ignore_strcmp(ap->defaultvalue, *ap->argval) == 0)) { printf(" (=default)"); } @@ -1238,37 +1243,45 @@ disp_vec_options(const char* vecname, arglist_t* ap) } } -ff_vecs_t* -find_vec(const char* vecname, const char** opts) +void validate_options(const QStringList& options, const arglist_t* args, const QString& name) { - char* v = xstrdup(vecname); - char* svecname = strtok(v, ","); - int found = 0; + for (const auto& option : options) { + const QString option_name = option.left(option.indexOf('=')); + bool valid = false; + for (auto ap = args; ap && ap->argstring; ap++) { + if (option_name.compare(ap->argstring, Qt::CaseInsensitive) == 0) { + valid = true; + break; + } + } + if (!valid) { + warning("'%s' is an unknown option to %s.\n", qPrintable(option_name), qPrintable(name)); + } + } +} - if (vecname == nullptr) { +ff_vecs_t* +find_vec(const QString& vecname) +{ + QStringList options = vecname.split(','); + if (options.isEmpty()) { fatal("A format name is required.\n"); } + const QString svecname = options.takeFirst(); for (const auto& vec : vec_list) { - if (case_ignore_strcmp(svecname, vec.name)) { + if (svecname.compare(vec.name, Qt::CaseInsensitive) != 0) { continue; } - const char* res = strchr(vecname, ','); - if (res) { - *opts = strchr(vecname, ',')+1; - } else { - *opts = nullptr; - } + validate_options(options, vec.vec->args, vec.name); if (vec.vec->args) { for (auto ap = vec.vec->args; ap->argstring; ap++) { - if (res) { - const char* opt = get_option(*opts, ap->argstring); - if (opt) { - found = 1; - assign_option(svecname, ap, opt); - xfree(opt); + if (!options.isEmpty()) { + const QString opt = get_option(options, ap->argstring); + if (!opt.isNull()) { + assign_option(vec.name, ap, CSTR(opt)); continue; } } @@ -1283,9 +1296,6 @@ find_vec(const char* vecname, const char** opts) } } } - if (opts && opts[0] && !found) { - warning("'%s' is an unknown option to %s.\n", *opts, vec.name); - } if (global_opts.debug_level >= 1) { disp_vec_options(vec.name, vec.vec->args); @@ -1294,7 +1304,6 @@ find_vec(const char* vecname, const char** opts) #if CSVFMTS_ENABLED // xcsv_setup_internal_style( nullptr ); #endif // CSVFMTS_ENABLED - xfree(v); vec.vec->name = vec.name; /* needed for session information */ return vec.vec; @@ -1305,25 +1314,18 @@ find_vec(const char* vecname, const char** opts) * is to search the list of xcsv styles. */ for (const auto& svec : style_list) { - if (case_ignore_strcmp(svecname, svec.name)) { + if (svecname.compare(svec.name, Qt::CaseInsensitive) != 0) { continue; } - const char* res = strchr(vecname, ','); - if (res) { - *opts = strchr(vecname, ',') + 1; - } else { - *opts = nullptr; - } + validate_options(options, vec_list[0].vec->args, svec.name); if (vec_list[0].vec->args) { for (auto ap = vec_list[0].vec->args; ap->argstring; ap++) { - if (res) { - const char* opt = get_option(*opts, ap->argstring); - if (opt) { - found = 1; - assign_option(svecname, ap, opt); - xfree(opt); + if (!options.isEmpty()) { + const QString opt = get_option(options, ap->argstring); + if (!opt.isNull()) { + assign_option(svec.name, ap, CSTR(opt)); continue; } } @@ -1339,10 +1341,6 @@ find_vec(const char* vecname, const char** opts) } } - if (opts && opts[0] && !found) { - warning("'%s' is an unknown option to %s.\n", *opts, svec.name); - } - if (global_opts.debug_level >= 1) { disp_vec_options(svec.name, vec_list[0].vec->args); } @@ -1350,7 +1348,6 @@ find_vec(const char* vecname, const char** opts) xcsv_setup_internal_style(svec.style_buf); #endif // CSVFMTS_ENABLED - xfree(v); vec_list[0].vec->name = svec.name; /* needed for session information */ return vec_list[0].vec; } @@ -1358,7 +1355,6 @@ find_vec(const char* vecname, const char** opts) /* * Not found. */ - xfree(v); return nullptr; } @@ -1366,44 +1362,31 @@ find_vec(const char* vecname, const char** opts) * Find and return a specific argument in an arg list. * Modelled approximately after getenv. */ -char* -get_option(const char* iarglist, const char* argname) +QString +get_option(const QStringList& options, const char* argname) { - const size_t arglen = strlen(argname); - char* rval = nullptr; - char* argp; + QString rval; - if (!iarglist) { - return nullptr; - } - - char* arglist = xstrdup(iarglist); - - for (char* arg = arglist; argp = strtok(arg, ","), nullptr != argp; arg = nullptr) { - if (0 == case_ignore_strncmp(argp, argname, arglen)) { + for (const auto& option : options) { + int split = option.indexOf('='); + const QString option_name = option.left(split); + if (option_name.compare(argname, Qt::CaseInsensitive) == 0) { /* * If we have something of the form "foo=bar" * return "bar". Otherwise, we assume we have * simply "foo" so we return that. */ - if (argp[arglen] == '=') { - rval = argp + arglen + 1; + if (split >= 0) { // we found an '='s. + rval = option.mid(split + 1); // not null, possibly empty + assert(!rval.isNull()); break; - } else if (argp[arglen] == '\0') { - rval = argp; + } else { + rval = option_name; // not null, possibly empty. + assert(!rval.isNull()); break; } } } - /* - * Return an offset into the allocated copy. - * The caller mustn't free or otherwise get froggy with - * this data. - */ - if (rval) { - rval = xstrdup(rval); - } - xfree(arglist); return rval; } @@ -1417,6 +1400,7 @@ sort_and_unify_vecs() { QVector svp; svp.reserve(vec_list.size() + style_list.size()); + /* Normal vecs are easy; populate the first part of the array. */ for (const auto& vec : vec_list) { vecs_t uvec = vec; @@ -1434,18 +1418,14 @@ sort_and_unify_vecs() uvec.vec = new ff_vecs_t; /* LEAK */ uvec.extensions = xcsv_file.extension; *uvec.vec = *vec_list[0].vec; /* Inherits xcsv opts */ - /* Reset file type to inherit ff_type from xcsv for everything - * except the xcsv format itself, which we leave as "internal" + /* Reset file type to inherit ff_type from xcsv. */ + uvec.vec->type = xcsv_file.type; + /* Skip over the first help entry for all but the + * actual 'xcsv' format - so we don't expose the + * 'full path to xcsv style file' argument to any + * GUIs for an internal format. */ - if (case_ignore_strcmp(svec.name, "xcsv")) { - uvec.vec->type = xcsv_file.type; - /* Skip over the first help entry for all but the - * actual 'xcsv' format - so we don't expose the - * 'full path to xcsv style file' argument to any - * GUIs for an internal format. - */ - uvec.vec->args++; - } + uvec.vec->args++; memset(&uvec.vec->cap, 0, sizeof(uvec.vec->cap)); switch (xcsv_file.datatype) { case unknown_gpsdata: @@ -1471,7 +1451,7 @@ sort_and_unify_vecs() * parse for help on available command line options. */ auto alpha = [](const vecs_t& a, const vecs_t& b)->bool { - return case_ignore_strcmp(a.desc, b.desc) < 0; + return QString::compare(a.desc, b.desc, Qt::CaseInsensitive) < 0; }; /* Now that we have everything in an array, alphabetize them */ @@ -1490,7 +1470,7 @@ disp_vecs() if (vec.vec->type == ff_type_internal) { continue; } - printf(VEC_FMT, vec.name, CSTR(vec.desc)); + printf(VEC_FMT, qPrintable(vec.name), qPrintable(vec.desc)); for (auto ap = vec.vec->args; ap && ap->argstring; ap++) { if (!(ap->argtype & ARGTYPE_HIDDEN)) printf(" %-18.18s %s%-.50s %s\n", @@ -1504,15 +1484,15 @@ disp_vecs() } void -disp_vec(const char* vecname) +disp_vec(const QString& vecname) { const auto svp = sort_and_unify_vecs(); for (const auto& vec : svp) { - if (case_ignore_strcmp(vec.name, vecname)) { + if (vecname.compare(vec.name, Qt::CaseInsensitive) != 0) { continue; } - printf(VEC_FMT, vec.name, CSTR(vec.desc)); + printf(VEC_FMT, qPrintable(vec.name), qPrintable(vec.desc)); for (auto ap = vec.vec->args; ap && ap->argstring; ap++) { if (!(ap->argtype & ARGTYPE_HIDDEN)) printf(" %-18.18s %s%-.50s %s\n", @@ -1552,7 +1532,7 @@ disp_v1(ff_type t) } static void -disp_v2(ff_vecs_t* v) +disp_v2(const ff_vecs_t* v) { for (auto& i : v->cap) { putchar((i & ff_cap_read) ? 'r' : '-'); @@ -1581,11 +1561,11 @@ name_option(uint32_t type) } static -void disp_help_url(const vecs_t& vec, arglist_t* arg) +void disp_help_url(const vecs_t& vec, const arglist_t* arg) { - printf("\t" WEB_DOC_DIR "/fmt_%s.html", vec.name); + printf("\t" WEB_DOC_DIR "/fmt_%s.html", CSTR(vec.name)); if (arg) { - printf("#fmt_%s_o_%s",vec.name, arg->argstring); + printf("#fmt_%s_o_%s", CSTR(vec.name), arg->argstring); } printf("\n"); } @@ -1598,7 +1578,7 @@ disp_v3(const vecs_t& vec) for (auto ap = vec.vec->args; ap && ap->argstring; ap++) { if (!(ap->argtype & ARGTYPE_HIDDEN)) { printf("option\t%s\t%s\t%s\t%s\t%s\t%s\t%s", - vec.name, + CSTR(vec.name), ap->argstring, ap->helpstring, name_option(ap->argtype), @@ -1639,11 +1619,11 @@ disp_formats(int version) if (version >= 2) { disp_v2(vec.vec); } - printf("%s\t%s\t%s%s%s\n", vec.name, + printf("%s\t%s\t%s%s%s\n", CSTR(vec.name), !vec.extensions.isEmpty() ? CSTR(vec.extensions) : "", CSTR(vec.desc), version >= 3 ? "\t" : "", - version >= 3 ? vec.parent : ""); + version >= 3 ? CSTR(vec.parent) : ""); if (version >= 3) { disp_v3(vec); } @@ -1654,26 +1634,28 @@ disp_formats(int version) } } -bool validate_args(const char* vecname, arglist_t* ap) +bool validate_args(const QString& name, const arglist_t* args) { bool ok = true; - for (; ap && ap->argstring; ap++) { - if (ap->argtype == ARGTYPE_INT) { - if (ap->defaultvalue && - ! is_integer(ap->defaultvalue)) { - Warning() << vecname << "Int option" << ap->argstring << "default value" << ap->defaultvalue << "is not an integer."; - ok = false; - } - if (ap->minvalue && - ! is_integer(ap->minvalue)) { - Warning() << vecname << "Int option" << ap->argstring << "minimum value" << ap->minvalue << "is not an integer."; - ok = false; - } - if (ap->maxvalue && - ! is_integer(ap->maxvalue)) { - Warning() << vecname << "Int option" << ap->argstring << "maximum value" << ap->maxvalue << "is not an integer."; - ok = false; + if (args != nullptr) { + for (auto ap = args; ap->argstring; ap++) { + if (ap->argtype == ARGTYPE_INT) { + if (ap->defaultvalue && + ! is_integer(ap->defaultvalue)) { + Warning() << name << "Int option" << ap->argstring << "default value" << ap->defaultvalue << "is not an integer."; + ok = false; + } + if (ap->minvalue && + ! is_integer(ap->minvalue)) { + Warning() << name << "Int option" << ap->argstring << "minimum value" << ap->minvalue << "is not an integer."; + ok = false; + } + if (ap->maxvalue && + ! is_integer(ap->maxvalue)) { + Warning() << name << "Int option" << ap->argstring << "maximum value" << ap->maxvalue << "is not an integer."; + ok = false; + } } } } -- 2.30.2